#include "StdAfx.h"
#include "MouseAnimator.h"
#include <math.h>
#include <process.h>


int MouseAnimator::AnimateMouse(int iX, int iY, int iV0, int iA)
{
	//get current pos
	POINT cur;
	GetCursorPos(&cur);

	//direction
	double dirx = iX - cur.x;
	double diry = iY - cur.y;

	double norm = sqrt(dirx*dirx + diry * diry);
	if(norm == 0) norm = 1;

	dirx /= norm;
	diry /= norm;
	
	//noise
	double dx = 0.07*iA/5;
	double dy = 0.07*iA/5;

	
	double vx = iV0/1000.0;
	double vy = iV0/1000.0;
	double a = iA/1000.0;
	double x = cur.x;
	double y = cur.y;


	int interval = 10;
	int time = 0;
	bool done = false;
	if(abs(iX - x) < 2 && abs(iY - y) < 2 ) done = true;
	while(!done)
	{
		//check if new direction != old direction - done animation
		double newdirx = iX - x;
		double newdiry = iY - y;

		double norm = sqrt(newdirx*newdirx + newdiry * newdiry);
		if(norm == 0) norm = 1;

		newdirx /= norm;
		newdiry /= norm;

		
		//move cursor
		x += vx*interval*newdirx;
		y += vy*interval*newdiry;
		SetCursorPos((int)x, (int)y);


		//update v
		vx += (a + (dx*(double)rand())/RAND_MAX - dx/2) * interval;	
		vy += (a + (dy*(double)rand())/RAND_MAX - dy/2) * interval;	


		//sleep
		Sleep(interval);
		time += interval;

		if(newdirx*dirx<0 || newdiry*diry < 0) 
		{			
			done = true;
		}
	}
	

	SetCursorPos(iX, iY);

	return time;
}


//----------------------------------------------------------------------------------------------------------------
unsigned int __stdcall MouseAnimator::ThreadFunc(void *iParams)
{
	if(!iParams) return 1;

	MouseAnimator *panimator = (MouseAnimator *)iParams;
	//copy params
	int x = panimator->X;
	int y = panimator->Y;
	int v = panimator->V;
	int a = panimator->A;
	MouseAnimatorCallback *callback = panimator->Callback;


	//send start event
	HANDLE start_event = CreateEvent(0, 0, 0, _T("mouse_animator_start_event"));
	SetEvent(start_event);
	CloseHandle(start_event);


	//animate
	int time = AnimateMouse(x, y, v, a);
	if(callback)
		callback->AnimationDone(time);

	return 0;
}


//----------------------------------------------------------------------------------------------------------------
void MouseAnimator::AnimateAsync(int iToXCoord, int iToYCoord, int iV, int iA, MouseAnimatorCallback *iCallback) 
{
	//create start event
	HANDLE start_event = CreateEvent(0, 0, 0, _T("mouse_animator_start_event"));

	
	X = iToXCoord;
	Y = iToYCoord;
	V = iV;
	A = iA;
	Callback = iCallback;


	//begin async
	uintptr_t res = _beginthreadex(0, 0, ThreadFunc, (void* )this, 0, 0);	
	bool succ = res != -1L;
	Thread = (HANDLE)res;


	//wait for starting	
	WaitForSingleObject(start_event, 3000);
	CloseHandle(start_event);
}


//----------------------------------------------------------------------------------------------------------------
int MouseAnimator::AnimateSync(int iToXCoord, int iToYCoord, int iV, int iA) const
{
	return AnimateMouse(iToXCoord, iToYCoord, iV, iA);
}